package com.youlu.campus.service.douyin;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.mongodb.client.result.UpdateResult;
import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.component.QiniuUtil;
import com.youlu.campus.entity.SystemNickNameAndHeaderImage;
import com.youlu.campus.entity.UserPO;
import com.youlu.campus.entity.VO.res.UserResponse;
import com.youlu.campus.entity.WechatMiniUserPO;
import com.youlu.campus.entity.domain.DecryptWechatMiniResult;
import com.youlu.campus.entity.douyin.DouYinMiniUserPO;
import com.youlu.campus.entity.douyin.dto.DouYinMiniDecryptDTO;
import com.youlu.campus.entity.douyin.dto.DouYinSessionDTO;
import com.youlu.campus.entity.douyin.dto.ThirdDecryptUserResult;
import com.youlu.campus.entity.douyin.dto.UserLoginDTO;
import com.youlu.campus.service.utils.CommonUtils;
import com.youlu.campus.service.utils.WebTokenUtils;
import com.youlu.campus.service.visitor.UserInfoExtendService;
import com.youlu.campus.service.visitor.VisitorUserService;
import com.youlu.campus.service.wechat.SystemNickNameAndHeaderImageService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

import java.util.*;


/**
 * @author : [dengbo]
 * @className : DouyinService
 * @description : [抖音服务]
 * @createTime : [2023/2/28 14:13]
 */
@Service
@Slf4j
public class DouYinUserService {
    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private DouYinApiService douYinApiService;

    @Autowired
    private VisitorUserService visitorUserService;

    @Autowired
    private ThirdTokenStoreService thirdTokenStoreService;

    @Autowired
    private UserInfoExtendService userInfoExtendService;

    @Autowired
    private SystemNickNameAndHeaderImageService systemNickNameAndHeaderImageService;

    @Autowired
    private QiniuUtil qiniuUtil;

//    @Autowired
//    private WechatConfigInfoService wechatConfigInfoService;

    public UserResponse login(UserLoginDTO dto) {
        log.info("dou yin mini login request param:{}", dto);
        if (StringUtils.isBlank(dto.getAppId()) || StringUtils.isAllBlank(dto.getCode(), dto.getAnonymousCode())) {
            throw new BusinessException("抖音小程序登陆参数错误");
        }
//        WechatConfigInfo configInfo = wechatConfigInfoService.find(dto.getAppId());
//        if (Objects.isNull(configInfo) || StringUtils.isBlank(configInfo.getAppSecret())) {
//            log.error("dou yin login query config is empty appId:{}",dto.getAppId());
//            throw new BusinessException("抖音小程序登陆参数错误");
//        }
//        dto.setAppSecret(configInfo.getAppSecret());
        DouYinSessionDTO douYinSession = douYinApiService.getSessionKeyInfo(dto);
        log.info("dou yin login appId:{} session info:{}", dto.getAppId(), douYinSession);
        if (douYinSession == null) {
            throw new BusinessException("小程序登录异常");
        }
        Query query = new Query().addCriteria(Criteria.where("openId").is(douYinSession.getOpenid()));
        DouYinMiniUserPO miniUserPO = mongoTemplate.findOne(query, DouYinMiniUserPO.class);
        Date now = new Date();
        if (miniUserPO == null) {
            miniUserPO = new DouYinMiniUserPO();
            miniUserPO.setAppId(dto.getAppId());
            miniUserPO.setOpenId(douYinSession.getOpenid());
            miniUserPO.setUnionId(douYinSession.getUnionid());
            miniUserPO.setId(null);
            miniUserPO.setCreatedTime(now);
        }
        String accountInfoId = "";
        Set<String> accountInfoIdList = new LinkedHashSet<>();
        String mobile = "";
        // 这里可以优化 账户id 或者id存在不查询，新增添加到其他相关的unionid账户中
        if (StringUtils.isNotBlank(douYinSession.getUnionid())) {
            Query query1 = new Query().addCriteria(Criteria.where("unionId").is(douYinSession.getUnionid()).and("openId").ne(douYinSession.getOpenid()));
            WechatMiniUserPO exist = mongoTemplate.findOne(query1, WechatMiniUserPO.class);
            if (exist != null) {
                log.info("wechat nini has same unionId:{} id:{}", exist.getUnionId(), exist.getId());
                accountInfoIdList.add(exist.getAccountInfoId());
                if (StringUtils.isBlank(miniUserPO.getAvatarUrl())) {
                    miniUserPO.setAvatarUrl(exist.getAvatarUrl());
                    miniUserPO.setNickName(exist.getNickName());
                }
            }
        }
        // 更新用户的
        if (StringUtils.isNotBlank(miniUserPO.getAccountInfoId())) {
            accountInfoId = miniUserPO.getAccountInfoId();
            UserPO user = visitorUserService.findUserByUserId(accountInfoId);
            if (Objects.nonNull(user) && StringUtils.isNotBlank(user.getMobile())) {
                mobile = user.getMobile();
            }
            accountInfoIdList.add(accountInfoId);
        } else {
            if (CollectionUtils.isEmpty(accountInfoIdList)) {
                UserPO saveUser = new UserPO();
                saveUser.setAppId(dto.getAppId());
                saveUser.setOpenId(douYinSession.getOpenid());
                saveUser.setUnionId(douYinSession.getUnionid());
                UserPO userExist = visitorUserService.saveOrUpdate(saveUser);
                accountInfoId = userExist.getId();
                accountInfoIdList.add(accountInfoId);
            } else {
                accountInfoId = accountInfoIdList.stream().findFirst().get();
            }
        }
        miniUserPO.setUpdatedTime(now);
        miniUserPO.setAccountInfoId(accountInfoId);
        miniUserPO.setAccountInfoIdList(accountInfoIdList);
        if (StringUtils.isNotBlank(mobile)) {
            miniUserPO.setMobile(mobile);
            miniUserPO.setCheckedMobile(true);
        }
        //保存sessionKey到redis
        thirdTokenStoreService.setSessionKey(dto.getAppId(), douYinSession.getOpenid(), douYinSession.getSessionKey());

        mongoTemplate.save(miniUserPO);
        UserResponse userResponse = new UserResponse();
        BeanUtils.copyProperties(miniUserPO, userResponse);
        userResponse.setOpenId(douYinSession.getOpenid());
        userResponse.setToken(WebTokenUtils.signToken(douYinSession.getOpenid()));
        return userResponse;
    }

    public DouYinMiniUserPO decryptUserData(DouYinMiniDecryptDTO decryptRequest) {
        log.info("dou yin decrypt request param:{}", JSON.toJSONString(decryptRequest));
        if (decryptRequest == null || StringUtils.isAnyBlank(decryptRequest.getOpenId(), decryptRequest.getAppId())) {
            log.error("dou yin decrypt:openId、appId is empty");
            throw new BusinessException("解密用户参数错误");
        }
        UserPO user = decryptRequest.getUserPO();
        if (user == null) {
            throw new BusinessException("用户未登录~");
        }
        decryptRequest.setOpenId(user.getOpenId());
        String key = thirdTokenStoreService.getSessionKey(decryptRequest.getAppId(), decryptRequest.getOpenId());
        if (StringUtils.isBlank(key)) {
            log.error("dou yin decrypt sessionKey get null", decryptRequest.getAppId(), decryptRequest.getOpenId());
            throw new BusinessException("获取sessionKey失败，请重新登录");
        }
        String sessionKey = key;
        log.info("appId:{},openId:{},sessionKey:{}", decryptRequest.getAppId(), decryptRequest.getOpenId(), sessionKey);
        //解密之后的用户信息
        String decrypt = null;
        try {
            decrypt = CommonUtils.douyinDecrypt(decryptRequest.getEncryptedData(), sessionKey, decryptRequest.getIv());
            log.info("appId:{},openId:{} dou yin decrypt result", decryptRequest.getAppId(), decryptRequest.getOpenId(), decrypt);
        } catch (Exception e) {
            log.warn("appId:{},openId:{} dou yin decrypt exception msg:{}", decryptRequest.getAppId(), decryptRequest.getOpenId(), e.getMessage());
            // 解析失败 从明文解析
            decrypt = decryptRequest.getRawData();
        }
        if (StringUtils.isEmpty(decrypt)) {
            throw new BusinessException("解析用户信息为空");
        }
        ThirdDecryptUserResult decryptData = JSON.parseObject(decrypt, ThirdDecryptUserResult.class);
        Update update = new Update();
        boolean isAuth = "1".equals(decryptRequest.getType());
        Query query = new Query().addCriteria(Criteria.where("openId").is(decryptRequest.getOpenId()));
        if (isAuth) {
            String currLog = user.getAvatarUrl();
            if(StringUtils.isBlank(currLog) || !currLog.startsWith("https://qiniu.gqgood.com")){
                currLog = getUpdateDouYinLogo(decryptData.getAvatarUrl());
                update.set("avatarUrl", currLog);
            }
            update.set("province", decryptData.getProvince());
            update.set("city", decryptData.getCity());
            update.set("country", decryptData.getCountry());
            update.set("nickName", decryptData.getNickName());
            update.set("gender", decryptData.getGender());
            update.set("authorized", true);
            update.set("binded", true);
            update.set("validLogo", true);
        } else {
            update.set("mobile", decryptData.getPhoneNumber());
            update.set("checkedMobile", true);
        }
        UpdateResult updateResult = mongoTemplate.updateFirst(query, update, DouYinMiniUserPO.class);
        log.info("dou yin openId:{} update user result:{}", decryptRequest.getOpenId(), updateResult.getModifiedCount());
        if (updateResult.getModifiedCount() > 0) {
            try {
                user.setMobile(decryptData.getPhoneNumber());
                user.setCity(decryptData.getCity());
                user.setProvince(decryptData.getProvince());
                user.setAvatarUrl(decryptData.getAvatarUrl());
                user.setNickName(decryptData.getNickName());
                user.setH5SignUp(Boolean.TRUE);
                userInfoExtendService.saveOrUpdate(user);
            } catch (Exception e) {
                log.error("dou yin update extend user error", user.getId(), e);
            }
        }
        DouYinMiniUserPO miniUserPO = new DouYinMiniUserPO();
        BeanUtils.copyProperties(user, miniUserPO);
        if (isAuth) {
            miniUserPO.setBinded(true);
        } else {
            miniUserPO.setCheckedMobile(true);
        }
        return miniUserPO;
    }

    public String getUpdateDouYinLogo(String avatarUrl){
        // 是否为空
        if(StringUtils.isBlank(avatarUrl)) {
            // 随机获取一张
            SystemNickNameAndHeaderImage image = systemNickNameAndHeaderImageService.getRandom();
            return image.getAvatarUrl();
        }
        // 已经存在非七牛存储的，更新到七牛
        String uploadUrl = qiniuUtil.uploadFileByUrl(avatarUrl, "","douyin-",false,null);
        List<String> contents = Lists.newArrayList("1","2");
        // 更新用户需要校验图片
        if(!contents.contains(uploadUrl)){
            // 上传成功则替换
           return uploadUrl;
        }
        SystemNickNameAndHeaderImage image = systemNickNameAndHeaderImageService.getRandom();
        return image.getAvatarUrl();
    }

    public DouYinMiniUserPO findByOpenId(String appId, String openId) {
        Query query = new Query().addCriteria(Criteria.where("openId").is(openId).and("appId").is(appId));
        DouYinMiniUserPO miniUserPO = mongoTemplate.findOne(query, DouYinMiniUserPO.class);
        return miniUserPO;
    }
}
